package main

import (
	"flag"
	"fmt"
	"log"
	"net"

	"github.com/pion/turn/v2"
	"gopkg.in/ini.v1"
)

type TurnConfig struct {
	publicIp   string
	listenPort int
	username   string
	password   string
	realm      string
}

func startTurn(config TurnConfig) {
	// udpListener
	udpListener, err := net.ListenPacket("udp4", fmt.Sprintf("%s:%d", "0.0.0.0", config.listenPort))
	if err != nil {
		log.Fatal(err.Error())
	}

	// userMaps
	userMaps := make(map[string][]byte)
	userMaps[config.username] = turn.GenerateAuthKey(config.username, config.realm, config.password)

	// create New TurnServer
	turn.NewServer(turn.ServerConfig{
		Realm: config.realm,
		AuthHandler: func(username, realm string, srcAddr net.Addr) (key []byte, ok bool) {
			log.Println("auth user: ", username)
			if key, ok := userMaps[username]; ok {
				return key, ok
			}
			return nil, false
		},
		PacketConnConfigs: []turn.PacketConnConfig{
			{
				PacketConn: udpListener,
				RelayAddressGenerator: &turn.RelayAddressGeneratorStatic{
					RelayAddress: net.ParseIP(config.publicIp),
					Address:      "0.0.0.0",
				},
			},
		},
	})

	log.Printf("turn server listen at ::%d\n", config.listenPort)

}

func main() {

	var configPath string

	flag.StringVar(&configPath, "c", "", "The turn server config file")

	flag.Parse()

	if configPath == "" {
		log.Fatal("Not found config file")
	}

	cfg, err := ini.Load(configPath)
	if err != nil {
		log.Fatal(err.Error())
	}

	listenPort, err := cfg.Section("turn").Key("listenPort").Int()
	if err != nil {
		log.Fatal(err.Error())
	}

	publicIp := cfg.Section("turn").Key("publicIp").String()

	username := cfg.Section("user").Key("username").String()
	password := cfg.Section("user").Key("password").String()
	realm := cfg.Section("user").Key("realm").String()

	if publicIp == "" || username == "" || password == "" {
		log.Fatal("Params Error")
	}

	config := TurnConfig{
		publicIp:   publicIp,
		listenPort: listenPort,
		username:   username,
		password:   password,
		realm:      realm,
	}

	startTurn(config)

	select {}

}
